package com.vadmin.vadminjava.service;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vadmin.vadminjava.aes.WXBizJsonMsgCrypt;
import com.vadmin.vadminjava.aes.WXBizMsgCrypt;
import com.vadmin.vadminjava.common.*;
import com.vadmin.vadminjava.db.DBUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/* ***********************************************************
 *
 * 企业微信的【客户变更】回调通知接收相关处理
 *
 * **********************************************************/
@Service
public class WxWorkNotifyCustomerService {

	org.slf4j.Logger logger = LoggerFactory.getLogger(WxWorkNotifyCustomerService.class.getName());

	@Autowired
	WxWorkClientService wxWorkService;
	@Autowired
	WxWorkCommon wxWorkCommon;
	@Autowired
	AdminLogService adminLogService;
	@Autowired
	WxUserMoneyService wxUserMoneyService;
	/**
	 * 接收外部客户变更通知
	 * @param paramJ 整个请求参数对象
	 * @param sReqData，流对象
	 * @return
	 */
	public String ExternalUserChange(JSONObject paramJ, String sReqData){

		//配置
		String sCorpID         = WxWorkConfig.CORP_ID;//企业id，在我的企业标签页里面
		String sToken          = WxWorkConfig.CUSTOMER_STOKEN;//设置接收事件服务器时的参数有
		String sEncodingAESKey = WxWorkConfig.CUSTOMER_SENCODINGAESKEY;//设置接收事件服务器时的参数有

		String sEchoStr = ""; //验证url时需要返回的明文

		try {
			WXBizJsonMsgCrypt wxcptJSON = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);//验证时用的，按json数据处理
			WXBizMsgCrypt     wxcptXML  = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);//推送消息用的，是xml数据处理方式

			// 解析出url上的参数值如下：
			String msgSignature = paramJ.getString("msg_signature");
			String timestamp    = paramJ.getString("timestamp");
			String nonce        = paramJ.getString("nonce");//随机数
			String echostr      = paramJ.getString("echostr");//加密的字符串。验证url时才有发送

			//判断是否是url验证，否则就是正式通知(狗日的企业微信后台保存回调域名时，是要先验证的)
			if(StringUtils.isNotEmpty(echostr)){
				sEchoStr = wxcptJSON.VerifyURL(msgSignature, timestamp, nonce, echostr);
				logger.info("进行了外部客户变更回调url设置的验证,返回的明文是："+sEchoStr);
			}else{

				////////////////////////////////////老衲///////////////////////////////////////
				//老衲主动添加黄浮驴
				//转成map：{ChangeType=add_external_contact, UserID=YangZhiCong, CreateTime=1645237759, WelcomeCode=MOhA9vky6gGnJjFTVM1Er2GLHdkrLcWDLlq-VyS1HFU, Event=change_external_contact, ExternalUserID=wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}
				//黄浮驴主动添加老衲
				//解密之后: <xml><ToUserName><![CDATA[ww9643385df2ca2627]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1645841094</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[change_external_contact]]></Event><ChangeType><![CDATA[add_external_contact]]></ChangeType><UserID><![CDATA[YangZhiCong]]></UserID><ExternalUserID><![CDATA[wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g]]></ExternalUserID><WelcomeCode><![CDATA[wKoTqolU2hi5uNW2XafyT6BrgX2K7nTvnfyKSVhzt6U]]></WelcomeCode></xml>
				//转成map：{ChangeType=add_external_contact, UserID=YangZhiCong, CreateTime=1645841094, WelcomeCode=wKoTqolU2hi5uNW2XafyT6BrgX2K7nTvnfyKSVhzt6U, Event=change_external_contact, ExternalUserID=wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}
				//添加蜡烛图
				//<xml><ToUserName><![CDATA[ww9643385df2ca2627]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1645772095</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[change_external_contact]]></Event><ChangeType><![CDATA[add_external_contact]]></ChangeType><UserID><![CDATA[YangZhiCong]]></UserID><ExternalUserID><![CDATA[wmJRSsWwAANl0_aEWc56wRpxvVMdUt-g]]></ExternalUserID><WelcomeCode><![CDATA[VSIUOTiyYIEu0veLuwnRl-0CUcIB0Q671-pMqml3tg0]]></WelcomeCode></xml>

				//老衲主动删除黄浮驴
				//解密之后: <xml><ToUserName><![CDATA[ww9643385df2ca2627]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1645840983</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[change_external_contact]]></Event><ChangeType><![CDATA[del_external_contact]]></ChangeType><UserID><![CDATA[YangZhiCong]]></UserID><ExternalUserID><![CDATA[wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g]]></ExternalUserID></xml>
				//转成map：{ChangeType=del_external_contact, UserID=YangZhiCong, CreateTime=1645840983, Event=change_external_contact, ExternalUserID=wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}
				//黄浮驴主动删除老衲
				//转成map：{ChangeType=del_follow_user,      UserID=YangZhiCong, CreateTime=1645238055, Event=change_external_contact, ExternalUserID=wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}


				////////////////////////////////////晴///////////////////////////////////////

				//晴添加蜡烛图
				//解密之后: <xml><ToUserName><![CDATA[ww9643385df2ca2627]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1645772095</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[change_external_contact]]></Event><ChangeType><![CDATA[add_external_contact]]></ChangeType><UserID><![CDATA[Qing]]></UserID><ExternalUserID><![CDATA[wmJRSsWwAANl0_aEWc56wRpxvVMdUt-g]]></ExternalUserID><WelcomeCode><![CDATA[VSIUOTiyYIEu0veLuwnRl-0CUcIB0Q671-pMqml3tg0]]></WelcomeCode></xml>
				//转成map：{ChangeType=add_external_contact, UserID=Qing, CreateTime=1645772095, WelcomeCode=VSIUOTiyYIEu0veLuwnRl-0CUcIB0Q671-pMqml3tg0, Event=change_external_contact, ExternalUserID=wmJRSsWwAANl0_aEWc56wRpxvVMdUt-g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}

				//蜡烛图主动删除晴
				//解密之后: <xml><ToUserName><![CDATA[ww9643385df2ca2627]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1645771720</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[change_external_contact]]></Event><ChangeType><![CDATA[del_external_contact]]></ChangeType><UserID><![CDATA[YangZhiCong]]></UserID><ExternalUserID><![CDATA[wmJRSsWwAANl0_aEWc56wRpxvVMdUt-g]]></ExternalUserID></xml>
				//转成map：{ChangeType=del_external_contact, UserID=YangZhiCong, CreateTime=1645771720, Event=change_external_contact, ExternalUserID=wmJRSsWwAANl0_aEWc56wRpxvVMdUt-g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}


				//晴添加黄浮驴
				//{ChangeType=add_external_contact, UserID=Qing, CreateTime=1646359303, WelcomeCode=-lqZ1QunYzFBASPqBhmCsWWChe-T-MXXniBAGi1lJoc, Event=change_external_contact, ExternalUserID=wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g, ToUserName=ww9643385df2ca2627, FromUserName=sys, MsgType=event}


				//输出
				//System.out.println("原始post数据流："+sReqData);
				String sMsg = wxcptXML.DecryptMsg(msgSignature, timestamp, nonce, sReqData);
				System.out.println("解密之后: " + sMsg);
				Map<String,String> xmlParse = xmlTool.xmlToMap(sMsg);
				System.out.println("转成map："+xmlParse);
				sEchoStr = xmlParse.toString();

				//客户数据与关系
				ExternalUserRelationHandle(xmlParse);
			}


		} catch (Exception ex) {
			logger.error("外部客户变更回调处理过程出错了{}",ex);
		} finally {

		}

		return sEchoStr;
	}


	//接收添加外部客户，测试
	public String ExternalUserChange2( String sReqData){
		String sEchoStr = ""; //验证url时需要返回的明文
		try {
			//输出
			//System.out.println("解密之后: " + sReqData);
			Map<String,String> xmlParse = xmlTool.xmlToMap(sReqData);
			//System.out.println("转成map："+xmlParse);
			sEchoStr = xmlParse.toString();
			//客户数据与关系
			ExternalUserRelationHandle(xmlParse);

		} catch (Exception ex) {
		} finally {
		}
		return sEchoStr;
	}

	/**
	 * 外部客户关系处理
	 * 由于xml中是大陀峰，所以下面可能用大陀峰
	 * 客户变量回调只有一次，并且企业微信中已经添加，如果这里处理出错就比较麻烦
	 * add_way表示添加客户的来源，有固定的值，而state表示此客户的渠道，可以由企业进行自定义的配置，请注意二者的不同。
	 * //todo 这个方法里面没有运用事务，要是出错就完蛋了。
	 * 值	含义
	 * 0	未知来源
	 * 1	扫描二维码
	 * 2	搜索手机号
	 * 3	名片分享
	 * 4	群聊
	 * 5	手机通讯录
	 * 6	微信联系人
	 * 8	安装第三方应用时自动添加的客服人员
	 * 9	搜索邮箱
	 * 10	视频号主页添加
	 * 201	内部成员共享
	 * 202	管理员/负责人分配
	 * @param xmlParse
	 */
	public void ExternalUserRelationHandle(Map<String,String> xmlParse) throws Exception {
		DBUtil dbUtil = new DBUtil();
		String UserID = xmlParse.get("UserID");//操作的员工
		String ChangeType = xmlParse.get("ChangeType");//类型
		String ExternalUserID = xmlParse.get("ExternalUserID");//外部客户的id

		String log = "";

		//先记录这件事
		adminLogService.write(
				LogEnum.EXTERNAL_CONTACT_EVENT.getName(), LogEnum.EXTERNAL_CONTACT_EVENT.getIndex(),
				JSONObject.toJSONString(xmlParse).replaceAll("[{}]",""));

		try {
			////////////////////////////  添加外部客户  //////////////////////////////////

			//todo 外部联系人免验证添加成员事件 add_half_external_contact

			if(ChangeType.equals("add_external_contact")){

				//<<<<<<<<<<<<<<<<获取外部客户的详情数据>>>>>>>>>>>>>>>>
				JSONObject _data       = wxWorkCommon.getExternalUserDataByHttp(ExternalUserID).getJSONObject("data");//由于返回的是给前端的格式，塞在data里面，这里要取出来
				//follow_user部分
				JSONArray  _FollowUserArray = _data.getJSONArray("follow_user"); //得到所属员工列表
				//System.out.println("回调添加客户：follow_user数组："+_FollowUserArray.toJSONString());
				Integer _FollowUserArraySize = _FollowUserArray.size(); //员工列表的个数

				JSONObject follow_user    = JSONObject.parseObject(_FollowUserArray.get(_FollowUserArraySize-1).toString());//这里的下标取决与follow_user数组是按照添加顺序从上往下的才行
				//System.out.println("回调添加客户：follow_user部分："+follow_user);
				String     oper_userid    = follow_user.getString("oper_userid");//发起添加的userid，如果成员主动添加，为成员的userid；如果是客户主动添加，则为客户的外部联系人userid；如果是内部成员共享/管理员分配，则为对应的成员/管理员userid
				String     userid         = follow_user.getString("userid");//添加了此外部联系人的企业成员userid
				String     add_way        = follow_user.getString("add_way");//该成员添加此客户的来源,见文档的客户详情-来源定义

				//external_contact部分
				JSONObject external_contact = _data.getJSONObject("external_contact");
				//System.out.println("回调添加客户：external_contact部分："+external_contact);
				String     external_userid  = external_contact.getString("external_userid");//外部用户id
				String     name             = external_contact.getString("name");//名字


				//查询是否有存在关系（这里的查询条件是以外部用户数据是否存在为条件，如果用到外部用户登录的功能，这里条件就要改, 要改为判断是否有关系表的关系存在）
				String sql1 = "select count(id) as count1 from wxwork_relation where external_userid = '"+ExternalUserID+"'";//获取行数
				Integer countR = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql1).getInteger("count1");//获取行数


				//经测试：在职继承，会先推送删除事件，走下面的删除逻辑，里面有删除关系，然后再推送添加事件。(注意，这个可能是在职继承会发生，可能离职继承只会推送添加事件)
				//进行关系处理>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				if(countR==0){ //如果没有找到关系（

					logger.info("外部客户变更回调处理>>>没有客户:{}与员工:{}的关系数据，将进行相关处理>>>>>>>>>>>",ExternalUserID,UserID);

					//先删除外部客户数据（主要是为了更新userid字段）
					String sqlDEU = "delete from wxwork_external_user where external_userid = '"+ExternalUserID+"'";
					dbUtil.executeUpdateTOnum(sqlDEU);

					//再重新写入外部客户数据表
					wxWorkCommon.insertExternalUserData(_data);

					//写入关系表
					String sqlR = "INSERT INTO `wxwork_relation`(`userid`, `external_userid`, `create_time`) VALUES ('"+UserID+"', '"+ExternalUserID+"', NOW())";
					dbUtil.insertOrUpdateInfoTONum(sqlR);

					//**********************************************/进行奖励处理***********************************************************//
					//**********************************************类型码已经校验***********************************************************//

					//查看有没这个员工加过这个客户的奖励事件
					String sqlC = "select count(id) as count1 from wxwork_user_money_log" +
							" where user_id='"+userid+"'" +
							" and external_userid ='"+external_userid+"' and event_code = '"+MoneyLogEnum.CUSTOMER_ADD.code+"'";//获取行数
					System.out.println("查看是否存在员工添加客户的奖励："+sqlC);
					Integer count = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil,sqlC).getInteger("count1");

					if(count==0){//进行分佣


						//操作资金数
						String _amount = WxWorkConfig.COMMISSION_CUSTOMER.toString();


						//找到员工的资金数据，进行计算
						String sql2 = "select * from wxwork_user where user_id = '" + userid + "'";
						Double _money = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql2).getDouble("money");
						String _moneyAfter = BigDecimalUtils.add(_money,_amount).toString();

						//在这个位置更新员工资金
						wxUserMoneyService.userMoneyChange(dbUtil,userid,_amount);//写入

						//记录明细
						JSONObject logParams = new JSONObject();
						logParams.put("user_id",userid);
						logParams.put("external_userid",external_userid);
						logParams.put("open_id","");
						logParams.put("money_before",_money);
						logParams.put("money",_amount);
						logParams.put("money_after",_moneyAfter);
						logParams.put("coupon_id","");//
						logParams.put("coupon_code","");
						logParams.put("event",      MoneyLogEnum.CUSTOMER_ADD.name);
						logParams.put("event_code", MoneyLogEnum.CUSTOMER_ADD.code);
						logParams.put("type",       MoneyLogEnum.TYPE_ADD.name);
						logParams.put("type_code",  MoneyLogEnum.TYPE_ADD.code);
						logParams.put("remark","进行了添加外部客户奖励");
						wxUserMoneyService.userMoneyLog(dbUtil,logParams);//写入

						logger.info("进行了员工{}添加客户{}的奖励处理",userid,external_userid);

					}else{
						logger.info("已经存在员工{}添加客户{}的奖励明细，不再进行奖励",userid,external_userid);
					}



					//记录
					log =  "外部客户变更回调处理>>>添加外部客户" + ExternalUserID + "，员工" + UserID + "，并进行关系创建，操作人：" + oper_userid;
					logger.info(log);
					adminLogService.write(LogEnum.EXTERNAL_CONTACT_ADD.getName(), LogEnum.EXTERNAL_CONTACT_ADD.getIndex(), log);


				}else{//存在员工与客户的关系

					logger.info("外部客户变更回调处理>>>数据库已经存在这个客户:{}和员工关系,操作员工：{},将进行add_way的判断处理>>>>>>>>>>",ExternalUserID,UserID);

					//判断客户详情中的的添加方式add_way
					if(add_way.equals("202")){
						logger.info("外部客户变更回调处理>>>员工：{}添加的客户：{} 添加方式add_way字段是202，将进行特殊处理>>>>>>>>>>>",UserID,ExternalUserID);

						//先删除外部客户数据
						String sqlDEU = "delete from wxwork_external_user where external_userid = '"+ExternalUserID+"'";
						dbUtil.executeUpdateTOnum(sqlDEU);

						//先删旧关系
						String sqlDR = "delete from wxwork_relation where external_userid = '"+ExternalUserID+"'";
						dbUtil.executeUpdateTOnum(sqlDR);

						//重新写入外部客户数据表（这里会更新userid字段的）
						wxWorkCommon.insertExternalUserData(_data);

						//重新写入关系表
						String sqlR = "INSERT INTO `wxwork_relation`(`userid`, `external_userid`, `create_time`) VALUES ('"+UserID+"', '"+ExternalUserID+"', NOW())";
						dbUtil.insertOrUpdateInfoTONum(sqlR);


						//记录
						log = "回调处理>>>添加外部客户，但已存在关系"+ExternalUserID+"，员工"+UserID+"，add_way是202，已经进行了相关特殊处理，操作人："+oper_userid;
						logger.info(log);
						adminLogService.write(LogEnum.EXTERNAL_CONTACT_ADD.getName(), LogEnum.EXTERNAL_CONTACT_ADD.getIndex(), log);


					}else{
						log = "外部客户变更回调处理>>>添加外部客户" + ExternalUserID + "，但已存在关系。员工" + UserID + "，add_way不是202，不是管理员分配，不再处理。操作人：" + oper_userid;
						logger.info(log);
						adminLogService.write(LogEnum.EXTERNAL_CONTACT_ADD.getName(), LogEnum.EXTERNAL_CONTACT_ADD.getIndex(), log);


					}
				}

				/////////////////////////////主动删除外部客户，或外部客户主动删除/////////////////////////
			}else if(ChangeType.equals("del_external_contact") || ChangeType.equals("del_follow_user")){

				//删除关系 (注意这里的条件,谁删谁)
				String sqlDR = "delete from wxwork_relation where userid='"+UserID+"' and external_userid='"+ExternalUserID+"'";
				dbUtil.executeUpdateTOnum(sqlDR);

				//不删除客户数据，详见任务，可能是怕有其它已存在的关联？
				logger.info("外部客户变更回调处理>>>客户删除类型:{}，客户:{}，员工：{}",ChangeType,ExternalUserID,UserID);
				adminLogService.write(LogEnum.EXTERNAL_CONTACT_DEL.getName(), LogEnum.EXTERNAL_CONTACT_DEL.getIndex(), "回调处理>>>客户删除类型"+ChangeType+"，客户"+ExternalUserID+"，员工"+UserID+"");

			}



		} catch (Exception ex) {
			logger.error("处理外部客户关系时出错了:{},回调数据：{}",ex,xmlParse);
			//throw ex;
		} finally {
			dbUtil.closeNoErr();
		}
	}
}
